import tkinter as tk
from tkinter import ttk, simpledialog, filedialog, messagebox
from tkinterdnd2 import TkinterDnD, DND_TEXT
import csv
from datetime import datetime


###############################################

#Logic

###############################################


# 加载数据
def load_data(file_path):
    # 打开文件
    with open(file_path, newline='') as file:
        # 创建csv读取器
        reader = csv.reader(file)
        # 遍历文件中的每一行
        for row in reader:
            # 插入并给行着色
            insert_and_color_row(row)

# 保存数据
def save_data():
    # 弹出保存对话框，获取文件路径
    file_path = filedialog.asksaveasfilename(defaultextension=".csv")

    # 如果用户取消保存，则直接返回
    if not file_path:
        return

    # 使用'w'模式打开文件，准备写入数据
    with open(file_path, 'w', newline='') as file:
        # 创建一个csv写入器
        writer = csv.writer(file)

        # 遍历树中的所有子节点
        for child_id in tree.get_children():
            # 获取子节点的值
            row = tree.item(child_id)['values']
            # 将值写入文件
            writer.writerow(row)

    # 弹出提示框，告知用户数据已保存成功
    messagebox.showinfo("Info", "Data saved successfully")

# 添加新数据
def add_new_data():
    # 弹出对话框提示用户输入数据
    user_input = simpledialog.askstring("Input", "Please enter some data (Priority, Content, Begin Time, End Time):")

    # 判断用户是否输入了数据
    if user_input:
        try:
            # 使用逗号分割用户输入的数据
            priority, content, begin_time, end_time = user_input.split(',')
            # 调用函数处理数据
            insert_and_color_row([priority, content, begin_time, end_time])
        except ValueError:
            # 如果分割失败，弹出错误提示框
            # 提示用户输入格式错误
            messagebox.showerror("Error", "Invalid input format. Please use: Priority, Content, Begin Time, End Time")

# 插入行并根据时间范围改变颜色
def insert_and_color_row(row):
    # 向树形控件中插入一行数据
    item_id = tree.insert('', 'end', values=row)

    # 解析行数据中的各个字段
    priority, content, begin_time, end_time = row

    # 获取当前时间
    now = datetime.now()
    current_time = now.strftime("%H:%M")
    current = datetime.strptime(current_time, "%H:%M")
    Begin = datetime.strptime(begin_time, "%H:%M")
    End = datetime.strptime(end_time, "%H:%M")

    # 根据时间范围设置颜色
    # 如果开始时间晚于当前时间，则标记为未来的事件，背景色设置为浅绿色
    if Begin > current:
        tree.tag_configure('future', background='lightgreen')
        tree.item(item_id, tags=('future',))
    # 如果结束时间早于当前时间，则标记为过去的事件，背景色设置为红色
    elif End < current:
        tree.tag_configure('past', background='red')
        tree.item(item_id, tags=('past',))
    # 如果开始时间和结束时间都在当前时间范围内，则标记为当前的事件，背景色设置为黄色
    else:
        tree.tag_configure('current', background='yellow')
        tree.item(item_id, tags=('current',))

# 删除数据
def remove_data():
    # 获取被选中的行索引
    selected_indices = tree.selection()

    # 如果存在被选中的行
    if selected_indices:
        # 逆序遍历被选中的行索引，避免在遍历过程中删除元素导致索引错乱
        for index in reversed(selected_indices):
            # 删除对应的行
            # 删除tree控件中被选中的行
            tree.delete(index)

# 编辑任务
def edit_task():
    # 获取选中的项目
    selected_item = tree.selection()
    # 如果没有选中的项目
    if not selected_item:
        # 弹出警告框，提示用户需要选择一个任务进行编辑
        messagebox.showwarning("Warning", "Please select a task to edit.")
        # 退出函数
        return

    # 获取选中项目的值
    item = tree.item(selected_item[0])['values']
    # 弹出对话框，让用户输入新的任务信息
    new_data = simpledialog.askstring("Edit Task", f"Current data: {item}\nEnter new data (Priority, Content, Begin Time, End Time):")

    # 如果用户输入了新的数据
    if new_data:
        try:
            # 将输入的数据按照逗号分隔，并分别赋值给新的变量
            new_priority, new_content, new_begin_time, new_end_time = new_data.split(',')
            # 更新树形控件中选中的项目的值
            tree.item(selected_item[0], values=(new_priority, new_content, new_begin_time, new_end_time))
        except ValueError:
            # 如果分隔失败，弹出错误框，提示用户输入格式不正确
            messagebox.showerror("Error", "Invalid input format. Please use: Priority, Content, Begin Time, End Time")

# 过滤任务
def filter_tasks():
    # 弹出对话框，让用户输入要过滤的优先级
    priority_filter = simpledialog.askstring("Filter Tasks", "Enter the priority to filter by (low, medium, high):")

    # 如果用户输入了优先级
    if priority_filter:
        # 遍历树中的所有子项
        for child_id in tree.get_children():
            # 获取当前子项的数据
            row = tree.item(child_id)['values']

            # 如果当前子项的优先级与用户输入的优先级不匹配
            if row[0] != priority_filter:
                # 将该子项从树中移除
                tree.detach(child_id)


# 创建看板
# 全局字典来存储卡片和它们的框架
cards = {}

# 创建卡片函数
def create_draggable_card(master, text, card_id):
    frame = tk.Frame(master, relief=tk.RAISED, borderwidth=1)
    label = tk.Label(frame, text=text, anchor='w', padx=10, pady=5)
    label.pack(fill=tk.X)

    def on_press(event):
        frame._drag_data = {"x": event.x, "y": event.y, "initial_x": frame.winfo_x(), "initial_y": frame.winfo_y()}

    def on_drag(event):
        delta_x = event.x - frame._drag_data["x"]
        delta_y = event.y - frame._drag_data["y"]
        frame.place(x=frame._drag_data["initial_x"] + delta_x, y=frame._drag_data["initial_y"] + delta_y)

    frame.bind("<Button-1>", on_press)
    frame.bind("<B1-Motion>", on_drag)

    # 存储卡片到全局字典中
    cards[card_id] = {"frame": frame, "original_master": master}

    return frame

# 拖放处理函数
def on_drop(event, target_frame):
    # 假设拖动的源是一个卡片
    source_widget = event.widget
    while not hasattr(source_widget, '_drag_data'):  # 查找具有_drag_data的父级（即卡片）
        source_widget = source_widget.master

    source_card_frame = cards[id(source_widget)]['frame']
    source_card_frame.place_forget()
    source_card_frame.pack(master=target_frame, pady=5, fill=tk.X)
    cards[id(source_widget)]['original_master'] = target_frame  # 更新原始框架

# 创建看板函数
def create_kanban_board():
    kanban_window = tk.Toplevel(root)
    kanban_window.title("Kanban Board")

    # 创建三个框架
    to_do_frame = tk.Frame(kanban_window, relief=tk.SUNKEN, borderwidth=1)
    in_progress_frame = tk.Frame(kanban_window, relief=tk.SUNKEN, borderwidth=1)
    done_frame = tk.Frame(kanban_window, relief=tk.SUNKEN, borderwidth=1)

    # 填充初始数据到相应的框架
    frames = {
        "To_Do": to_do_frame,
        "In Progress": in_progress_frame,
        "Done": done_frame
    }

    for frame_name, frame in frames.items():
        label = tk.Label(frame, text=frame_name, bg='lightblue', font=('Arial', 12, 'bold'))
        label.pack(fill=tk.X)
        frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        frame.drop_target_register(DND_TEXT)
        frame.dnd_bind('<<Drop>>', lambda e, f=frame: on_drop(e, f))

    # 添加初始任务到To_Do列表（示例）
    card_id_1 = id(to_do_frame)  # 临时使用框架ID作为卡片ID（实际应用中应使用更稳定的ID）
    card_frame_1 = create_draggable_card(to_do_frame, "Initial Task", card_id_1)
    card_frame_1.pack(pady=5, fill=tk.X)

###############################################

#UI

###############################################


# 创建主窗口
root = TkinterDnD.Tk()
root.title("To-Do List with Kanban Board")

# 创建按钮
load_button = tk.Button(root, text="Load Data", command=lambda: load_data(filedialog.askopenfilename()))
load_button.pack(side=tk.LEFT, padx=5, pady=5)

save_button = tk.Button(root, text="Save Data", command=save_data)
save_button.pack(side=tk.RIGHT, padx=5, pady=5)

add_button = tk.Button(root, text="Add New Data", command=add_new_data)
add_button.pack(pady=10)

remove_button = tk.Button(root, text="Remove Data", command=remove_data)
remove_button.pack()

edit_button = tk.Button(root, text="Edit Task", command=edit_task)
edit_button.pack(pady=10)

filter_button = tk.Button(root, text="Filter Tasks", command=filter_tasks)
filter_button.pack(pady=10)

kanban_button = tk.Button(root, text="Create Kanban Board", command=create_kanban_board)
kanban_button.pack(pady=10)

# 创建 Treeview 控件，并指定列名
tree = ttk.Treeview(root, columns=("Priority", "Content", "Begin Time", "End Time"), show="headings")
tree.heading("Priority", text="Priority")
tree.heading("Content", text="Content")
tree.heading("Begin Time", text="Begin Time")
tree.heading("End Time", text="End Time")

# 设置每列的宽度
tree.column("Priority", width=50)
tree.column("Content", width=200)
tree.column("Begin Time", width=100)
tree.column("End Time", width=100)

# 添加滚动条
vsb = ttk.Scrollbar(root, orient="vertical", command=tree.yview)
hsb = ttk.Scrollbar(root, orient="horizontal", command=tree.xview)
tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)

vsb.pack(side='right', fill='y')
hsb.pack(side='bottom', fill='x')

tree.pack(expand=True, fill=tk.BOTH)

# 运行主循环
root.mainloop()